package utiles
{
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	import mx.utils.ObjectUtil;
	import mx.utils.StringUtil;

	public class VOHelper
	{
		public static function setVOData(source:Object, dest:Object, warning:Boolean = false):void
		{
			// if source or dest is null, nothing to do.
			if (!source || !dest)
				return;
			
			var classInfo:Object = ObjectUtil.getClassInfo(source);
			var isDestDynamic:Boolean = ObjectUtil.getClassInfo(dest).dynamic;
			var properties:Array = classInfo.properties;
			for each (var prop:QName in properties)
			{
				var propName:String = prop.localName;
				
				// if dest has not the same property with src ... 
				if (!dest.hasOwnProperty(propName))
				{
					if (!isDestDynamic)
					{
						if (warning)
							trace(StringUtil.substitute("Warning: 设置属性时遇到目标属性不存在的问题 {0}::{1}",
								getQualifiedClassName(dest), propName));
						continue;
					}
				}
				
				var value:* = source[propName];
				var stype:String = typeof(value);
				var dtype:String = typeof(dest[propName]);
				if (dtype != stype && dest[propName] != null) // dest[propName] != null 目的仅为保护 String 类型, 其他类型的 null 会抛出运行时错误
				{
					if (warning)
						trace(StringUtil.substitute("Warning: 设置属性时遇到属性类型不一致的问题 {0}::{1} (type {2} to {3})",
							getQualifiedClassName(dest), propName, stype, dtype));
					continue;
				}

				switch (stype)
				{
					case "number":
					case "string":
					case "function":
					case "xml":
					case "boolean":
						dest[propName] = value;
						break;
					case "object":
						if (value == null)
						{
							dest[propName] = null;
						}
						else if (value is Array || getQualifiedClassName(value).indexOf("__AS3__.vec::Vector.") == 0)	// value is an Array, dest[prop] should be a Vector or an Array too. 
						{
							var className:String = getQualifiedClassName(dest[propName]);
							
							if (dest[propName] is Array)	// array
							{
								dest[propName].length = 0;
								for each (var item:* in value)
								{
									dest[propName].push(item);
								}
							} else if (className.indexOf("__AS3__.vec::Vector.") == 0)	// vector
							{
								var contentClassName:String = className.slice(21, -1); // "__AS3__.vec::Vector.<".length equals 21;
								dest[propName].length = 0;
								for each (item in value)
								{
									var contentClass:Class = Class(getDefinitionByName(contentClassName));
									var content:* = new contentClass();
									if ( typeof(content) == "object" )
										setVOData(item, content);
									else
										content = item;
									dest[propName].push(content);
								}
							} else
							{
								if (warning)
									trace(StringUtil.substitute("Warning: 为数组设置属性时遇到属性类型不一致的问题 {0}::{1} (type {2} to {3})",
										getQualifiedClassName(dest), propName, stype, dtype));
							}
						} else
						{
							setVOData(value, dest[propName]);
						}
						break;
					default: break;
				}
			}
		}
	}
}